﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.MountAndBlade.View.Scripts.MapColorGradeManager
// Assembly: TaleWorlds.MountAndBlade.View, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 61152EB8-513B-4D4A-8AC0-0D1465C6CF6C
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\Modules\Native\bin\Win64_Shipping_Client\TaleWorlds.MountAndBlade.View.dll

using System.Collections.Generic;
using System.Xml;
using TaleWorlds.Engine;
using TaleWorlds.Library;
using TaleWorlds.ObjectSystem;

#nullable disable
namespace TaleWorlds.MountAndBlade.View.Scripts
{
  public class MapColorGradeManager : ScriptComponentBehavior
  {
    public bool ColorGradeEnabled;
    public bool AtmosphereSimulationEnabled;
    public float TimeOfDay;
    public float SeasonTimeFactor;
    private string colorGradeGridName = "worldmap_colorgrade_grid";
    private const int colorGradeGridSize = 262144;
    private byte[] colorGradeGrid = new byte[262144];
    private Dictionary<byte, string> colorGradeGridMapping = new Dictionary<byte, string>();
    private MapColorGradeManager.ColorGradeBlendRecord primaryTransitionRecord;
    private MapColorGradeManager.ColorGradeBlendRecord secondaryTransitionRecord;
    private byte lastColorGrade;
    private Vec2 terrainSize = new Vec2(1f, 1f);
    private string defaultColorGradeTextureName = "worldmap_colorgrade_stratosphere";
    private const float transitionSpeedFactor = 1f;
    private float lastSceneTimeOfDay;

    private void Init()
    {
      if (this.Scene.ContainsTerrain)
      {
        Vec2i nodeDimension;
        float nodeSize;
        this.Scene.GetTerrainData(out nodeDimension, out nodeSize, out int _, out int _);
        this.terrainSize.x = (float) nodeDimension.X * nodeSize;
        this.terrainSize.y = (float) nodeDimension.Y * nodeSize;
      }
      this.colorGradeGridMapping.Add((byte) 1, this.defaultColorGradeTextureName);
      this.colorGradeGridMapping.Add((byte) 2, "worldmap_colorgrade_night");
      this.ReadColorGradesXml();
      MBMapScene.GetColorGradeGridData(this.Scene, this.colorGradeGrid, this.colorGradeGridName);
    }

    protected override void OnInit()
    {
      base.OnInit();
      this.Init();
    }

    protected override void OnEditorInit()
    {
      base.OnEditorInit();
      this.Init();
      this.TimeOfDay = this.Scene.TimeOfDay;
      this.lastSceneTimeOfDay = this.TimeOfDay;
    }

    public override ScriptComponentBehavior.TickRequirement GetTickRequirement()
    {
      return ScriptComponentBehavior.TickRequirement.Tick;
    }

    protected override void OnTick(float dt)
    {
      this.TimeOfDay = this.Scene.TimeOfDay;
      this.SeasonTimeFactor = MBMapScene.GetSeasonTimeFactor(this.Scene);
      this.ApplyAtmosphere(false);
      this.ApplyColorGrade(dt);
    }

    protected override void OnEditorTick(float dt)
    {
      if ((double) this.Scene.TimeOfDay != (double) this.lastSceneTimeOfDay)
      {
        this.TimeOfDay = this.Scene.TimeOfDay;
        this.lastSceneTimeOfDay = this.TimeOfDay;
      }
      if (this.Scene.ContainsTerrain)
      {
        Vec2i nodeDimension;
        float nodeSize;
        this.Scene.GetTerrainData(out nodeDimension, out nodeSize, out int _, out int _);
        this.terrainSize.x = (float) nodeDimension.X * nodeSize;
        this.terrainSize.y = (float) nodeDimension.Y * nodeSize;
      }
      else
      {
        this.terrainSize.x = 1f;
        this.terrainSize.y = 1f;
      }
      if (this.AtmosphereSimulationEnabled)
      {
        this.TimeOfDay += dt;
        if ((double) this.TimeOfDay >= 24.0)
          this.TimeOfDay -= 24f;
        this.ApplyAtmosphere(false);
      }
      if (!this.ColorGradeEnabled)
        return;
      this.ApplyColorGrade(dt);
    }

    protected override void OnEditorVariableChanged(string variableName)
    {
      base.OnEditorVariableChanged(variableName);
      switch (variableName)
      {
        case "ColorGradeEnabled":
          if (this.ColorGradeEnabled)
            break;
          this.Scene.SetColorGradeBlend("", "", -1f);
          this.lastColorGrade = (byte) 0;
          break;
        case "TimeOfDay":
          this.ApplyAtmosphere(false);
          break;
        case "SeasonTimeFactor":
          this.ApplyAtmosphere(false);
          break;
      }
    }

    private void ReadColorGradesXml()
    {
      XmlDocument mergedXmlForNative = MBObjectManager.GetMergedXmlForNative("soln_worldmap_color_grades", out List<string> _);
      if (mergedXmlForNative == null)
        return;
      XmlNode xmlNode1 = mergedXmlForNative.SelectSingleNode("worldmap_color_grades");
      if (xmlNode1 == null)
        return;
      XmlNode xmlNode2 = xmlNode1.SelectSingleNode("color_grade_grid");
      if (xmlNode2 != null && xmlNode2.Attributes["name"] != null)
        this.colorGradeGridName = xmlNode2.Attributes["name"].Value;
      XmlNode xmlNode3 = xmlNode1.SelectSingleNode("color_grade_default");
      if (xmlNode3 != null && xmlNode3.Attributes["name"] != null)
      {
        this.defaultColorGradeTextureName = xmlNode3.Attributes["name"].Value;
        this.colorGradeGridMapping[(byte) 1] = this.defaultColorGradeTextureName;
      }
      XmlNode xmlNode4 = xmlNode1.SelectSingleNode("color_grade_night");
      if (xmlNode4 != null && xmlNode4.Attributes["name"] != null)
        this.colorGradeGridMapping[(byte) 2] = xmlNode4.Attributes["name"].Value;
      XmlNodeList xmlNodeList = xmlNode1.SelectNodes("color_grade");
      if (xmlNodeList == null)
        return;
      foreach (XmlNode xmlNode5 in xmlNodeList)
      {
        byte result;
        if (xmlNode5.Attributes["name"] != null && xmlNode5.Attributes["value"] != null && byte.TryParse(xmlNode5.Attributes["value"].Value, out result))
          this.colorGradeGridMapping[result] = xmlNode5.Attributes["name"].Value;
      }
    }

    public void ApplyAtmosphere(bool forceLoadTextures)
    {
      this.TimeOfDay = MBMath.ClampFloat(this.TimeOfDay, 0.0f, 23.99f);
      this.SeasonTimeFactor = MBMath.ClampFloat(this.SeasonTimeFactor, 0.0f, 1f);
      MBMapScene.SetFrameForAtmosphere(this.Scene, this.TimeOfDay * 10f, this.Scene.LastFinalRenderCameraFrame.origin.z, forceLoadTextures);
      float valueFrom = 0.55f;
      float valueTo = -0.1f;
      float seasonTimeFactor = this.SeasonTimeFactor;
      MBMapScene.SetTerrainDynamicParams(this.Scene, new Vec3(y: 0.65f)
      {
        x = MBMath.Lerp(valueFrom, valueTo, seasonTimeFactor)
      });
    }

    public void ApplyColorGrade(float dt)
    {
      Vec3 origin = this.Scene.LastFinalRenderCameraFrame.origin;
      float num1 = 1f;
      int num2 = MathF.Floor((float) ((double) origin.x / (double) this.terrainSize.X * 512.0));
      int num3 = MathF.Floor((float) ((double) origin.y / (double) this.terrainSize.Y * 512.0));
      int num4 = MBMath.ClampIndex(num2, 0, 512);
      byte key = this.colorGradeGrid[MBMath.ClampIndex(num3, 0, 512) * 512 + num4];
      if ((double) origin.z > 400.0)
        key = (byte) 1;
      if ((double) this.TimeOfDay > 22.0 || (double) this.TimeOfDay < 2.0)
        key = (byte) 2;
      if (MBMapScene.GetApplyRainColorGrade() && (double) origin.z < 50.0)
      {
        key = (byte) 160;
        num1 = 0.2f;
      }
      if ((int) this.lastColorGrade != (int) key)
      {
        string str1 = "";
        string str2 = "";
        if (!this.colorGradeGridMapping.TryGetValue(this.lastColorGrade, out str1))
          str1 = this.defaultColorGradeTextureName;
        if (!this.colorGradeGridMapping.TryGetValue(key, out str2))
          str2 = this.defaultColorGradeTextureName;
        if (this.primaryTransitionRecord == null)
          this.primaryTransitionRecord = new MapColorGradeManager.ColorGradeBlendRecord()
          {
            color1 = str1,
            color2 = str2,
            alpha = 0.0f
          };
        else
          this.secondaryTransitionRecord = new MapColorGradeManager.ColorGradeBlendRecord()
          {
            color1 = this.primaryTransitionRecord.color2,
            color2 = str2,
            alpha = 0.0f
          };
        this.lastColorGrade = key;
      }
      if (this.primaryTransitionRecord == null)
        return;
      if ((double) this.primaryTransitionRecord.alpha < 1.0)
      {
        this.primaryTransitionRecord.alpha = MathF.Min(this.primaryTransitionRecord.alpha + dt * (1f / num1), 1f);
        this.Scene.SetColorGradeBlend(this.primaryTransitionRecord.color1, this.primaryTransitionRecord.color2, this.primaryTransitionRecord.alpha);
      }
      else
      {
        this.primaryTransitionRecord = (MapColorGradeManager.ColorGradeBlendRecord) null;
        if (this.secondaryTransitionRecord == null)
          return;
        this.primaryTransitionRecord = new MapColorGradeManager.ColorGradeBlendRecord(this.secondaryTransitionRecord);
        this.secondaryTransitionRecord = (MapColorGradeManager.ColorGradeBlendRecord) null;
      }
    }

    private class ColorGradeBlendRecord
    {
      public string color1;
      public string color2;
      public float alpha;

      public ColorGradeBlendRecord()
      {
        this.color1 = "";
        this.color2 = "";
        this.alpha = 0.0f;
      }

      public ColorGradeBlendRecord(MapColorGradeManager.ColorGradeBlendRecord other)
      {
        this.color1 = other.color1;
        this.color2 = other.color2;
        this.alpha = other.alpha;
      }
    }
  }
}
